package com.gotop.system.service.impl.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gotop.common.constant.DefaultConstant;
import com.gotop.common.node.ForestNodeMerger;
import com.gotop.common.utils.auth.CemUser;
import com.gotop.entity.system.Menu;
import com.gotop.entity.system.RoleMenu;
import com.gotop.mapper.system.MenuDao;
import com.gotop.system.service.system.IMenuService;
import com.gotop.system.service.system.IRoleMenuService;
import com.gotop.system.wrapper.MenuWrapper;
import com.gotop.vo.system.MenuVO;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: cem
 * @description:
 * @author: superfish
 * @create: 2020-12-22 10:28
 **/
@Service
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuDao, Menu> implements IMenuService {

    @Autowired
    private MenuDao menuDao;

    @Autowired
    private IRoleMenuService roleMenuService;

    @Override
    public List<Menu> list(Map<String, Object> menu) {
        return menuDao.list(menu);
    }

    @Override
    public List<MenuVO> tree() {
        final List<MenuVO> tree = baseMapper.tree();
        return ForestNodeMerger.merge(tree);
    }

    @Override
    public List<MenuVO> routes(String roleId) {
        if (StringUtils.isBlank(roleId)) {
            return null;
        }
        List<Menu> allMenus = baseMapper.allMenu();

        List<Menu> roleMenus;
        if (StringUtils.isEmpty(roleId)) {
            roleMenus = baseMapper.roleMenu(Arrays.asList(new Long[0]));
        } else {
            final String[] arr = roleId.split(",");
            Long[] longs = new Long[arr.length];
            for (int i = 0; i < arr.length; ++i) {
                Long v = Long.parseLong(arr[i]);
                longs[i] = v;
            }
            roleMenus = baseMapper.roleMenu(Arrays.asList(longs));
        }
        List<Menu> routes = new LinkedList<>(roleMenus);
        roleMenus.forEach(roleMenu -> recursion(allMenus, routes, roleMenu));
        routes.sort(Comparator.comparing(Menu::getSort));
        MenuWrapper menuWrapper = new MenuWrapper();
        List<Menu> collect = routes.stream().filter(x -> x.getCategory() == 1).collect(Collectors.toList());
        return menuWrapper.listNodeVO(collect);

    }

    @Override
    public List<MenuVO> buttons(String roleId) {
        List<Menu> buttons;
        if (StringUtils.isEmpty(roleId)) {
            buttons = baseMapper.buttons(Arrays.asList(new Long[0]));
        } else {
            final String[] arr = roleId.split(",");
            Long[] longs = new Long[arr.length];
            for (int i = 0; i < arr.length; ++i) {
                Long v = Long.parseLong(arr[i]);
                longs[i] = v;
            }
            buttons = baseMapper.buttons(Arrays.asList(longs));
        }
        MenuWrapper menuWrapper = new MenuWrapper();
        return menuWrapper.listNodeVO(buttons);
    }

    @Override
    public Menu getOne(Menu menu) {
        return menuDao.selectOne(new LambdaQueryWrapper<Menu>().eq(Menu::getId, menu.getId()));
    }

    @Override
    public List<MenuVO> grantTree(CemUser user) {
        final String[] split = user.getRoleId().split(",");
        List<Long> longs = new LinkedList<>();
        for (String s : split) {
            longs.add(Long.parseLong(s));
        }
        return ForestNodeMerger.merge(user.getTenantId().equals(DefaultConstant.ADMIN_TENANT_ID) ? baseMapper.grantTree() : baseMapper.grantTreeByRole(longs));
    }

    @Override
    public List<String> roleTreeKeys(String roleIds) {
        final String[] split = roleIds.split(",");
        List<RoleMenu> roleMenus = roleMenuService.list(Wrappers.<RoleMenu>query().lambda().in(RoleMenu::getRoleId, Arrays.asList(split)));
        return roleMenus.stream().map(roleMenu -> String.valueOf(roleMenu.getMenuId())).collect(Collectors.toList());
    }

    public void recursion(List<Menu> allMenus, List<Menu> routes, Menu roleMenu) {
        Optional<Menu> menu = allMenus.stream().filter(x -> String.valueOf(x.getId()).equals(String.valueOf(roleMenu.getParentId()))).findFirst();
        if (menu.isPresent()) {
            final Menu menue = menu.get();
            if (!routes.contains(menue)) {
                routes.add(menu.get());
                recursion(allMenus, routes, menu.get());
            }
        }
    }
}
